#include "main.h"
DEBUG

// 容量定义
#define CAED_SIZE 10   // 卡片列表大小
#define BUFFER_SIZE 20 // 缓冲区域大小

// 蓝牙命令
#define CODE_ANSWER 0xff        // 回复信息命令
#define CODE_ADD_CARD 0x01      // 新增卡片命令
#define CODE_REMOVE_CARD 0x02   // 删除卡片命令
#define CODE_OPEN_CURTAIN 0x03  // 打开窗帘命令
#define CODE_CLOSE_CURTAIN 0x04 // 关闭窗帘命令

// 蓝牙数据
#define CODE_DATA_ERROR 0x00000000   // 命令执行成功
#define CODE_DATA_SUCCESS 0x00000001 // 命令执行失败

// 步进电机
#define STEPMOTOR_ANGLE 180 // 步进电机角度

// 存储地址
#define FLASH_CARD_ADDR 0x1ff // 卡片信息地址

/**
 * @name 卡片列表
 * @struct
 */
#pragma pack(1)
typedef struct tagCARD_LIST {
    uint32_t length;                // 列表长度
    READCARD_CARD cards[CAED_SIZE]; // 卡片列表
} CARD_LIST, *PCARD_LIST;
#pragma pack()

GY_39_ENV env = {0};                      // 环境数据
int32_t stepMotor = 0;                    // 步进电机
BLUETOOTH_MSG msg = {0};                  // 蓝牙消息
READCARD_CARD card = {0};                 // 卡片信息
CARD_LIST cardList = {0};                 // 卡片列表
void (*stepMotorControls[2])(void) = {0}; // 电机控制[顺时针、逆时针]

/**
 * @name 初始化
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void init(void) {
    // 滴答计时
    sysTick_init();
    // LED
    led_init();
    // GY39
    gy39_init();
    // OLED
    oled_init();
    // 外部存储
    flash_init();
    // 调试串口
    debug_init();
    // 双频读卡
    readCard_init();
    // 蓝牙模块
    bluetooth_init();
    // 步进电机
    stepMotor_init();
    // 中断处理
    interrupt_init();
}

/**
 * @name 中断处理
 * @description
 * @function
 * @returns {*}
 * @requires []
 */
void interrupt(void) {
    // 控制电机
    if (stepMotor > 0)
        stepMotorControls[0](), --stepMotor; // 顺时针
    else
        stepMotorControls[1](), ++stepMotor; // 逆时针
}

int main(void) {
    uint32_t i = 0;
    BLUETOOTH_MSG message = {0};
    char buf[BUFFER_SIZE] = {0};
    READCARD_CARD readcardCard = {0};
    // 初始化
    init();
    // 中断控制
    interrupt_register(interrupt);
    // 读取卡片
    flash_read((uint8_t *)&cardList, FLASH_CARD_ADDR, sizeof(cardList));
    // 步进电机
    stepMotorControls[0] = stepMotor_control(STEPMOTOR_DIRECTION_CW, STEPMOTOR_PE_AB);
    stepMotorControls[1] = stepMotor_control(STEPMOTOR_DIRECTION_CCW, STEPMOTOR_PE_AB);
    while (1) {
        // 读取蓝牙
        msg = bluetooth_recv();
        // 读取卡片
        card = readCard_recv();
        // 解析蓝牙
        if (msg.type) {
            switch (msg.type) {
            case CODE_ADD_CARD: // 新增卡片
                readcardCard.cardType = msg.msg & 0xff;
                readcardCard.cardID = bluetooth_recv().msg;
                if (cardList.length < CAED_SIZE) {
                    cardList.cards[cardList.length++] = readcardCard;
                    // 回复执行成功
                    message.type = CODE_ANSWER;
                    message.msg = CODE_DATA_SUCCESS;
                    bluetooth_send(message);
                } else {
                    // 回复执行失败
                    message.type = CODE_ANSWER;
                    message.msg = CODE_DATA_ERROR;
                    bluetooth_send(message);
                }
                break;
            case CODE_REMOVE_CARD: // 删除卡片
                readcardCard.cardType = msg.msg & 0xff;
                readcardCard.cardID = bluetooth_recv().msg;
                for (i = 0; i < cardList.length; ++i)
                    if (cardList.cards[i].cardType == readcardCard.cardType && cardList.cards[i].cardID == readcardCard.cardID)
                        break;
                if (i < cardList.length) {
                    while (i < cardList.length - 1) {
                        cardList.cards[i] = cardList.cards[i + 1];
                        ++i;
                    }
                    --cardList.length;
                    // 回复执行成功
                    message.type = CODE_ANSWER;
                    message.msg = CODE_DATA_SUCCESS;
                    bluetooth_send(message);
                } else {
                    // 回复执行失败
                    message.type = CODE_ANSWER;
                    message.msg = CODE_DATA_ERROR;
                    bluetooth_send(message);
                }
                break;
            case CODE_OPEN_CURTAIN: // 打开窗帘
                stepMotor = STEPMOTOR_ANGLE;
                // 回复执行成功
                message.type = CODE_ANSWER;
                message.msg = CODE_DATA_SUCCESS;
                bluetooth_send(message);
                break;
            case CODE_CLOSE_CURTAIN: // 关闭窗帘
                stepMotor = -STEPMOTOR_ANGLE;
                // 回复执行成功
                message.type = CODE_ANSWER;
                message.msg = CODE_DATA_SUCCESS;
                bluetooth_send(message);
                break;
            default:
                // 回复执行失败
                message.type = CODE_ANSWER;
                message.msg = CODE_DATA_ERROR;
                bluetooth_send(message);
                break;
            }
        }
        // 检测卡片
        if (card.cardType) {
            // 查找卡片
            for (i = 0; i < cardList.length; ++i)
                if (cardList.cards[i].cardType == card.cardType && cardList.cards[i].cardID == card.cardID)
                    break;
            // 匹配成功
            if (i < CAED_SIZE)
                stepMotor = STEPMOTOR_ANGLE; // 打开大门
        }
        // 环境数据
        env = gy39_recv();
        // 显示数据
        sprintf(buf, "Lux: %d", env.Lux / 100);
        oled_showASCIIString(5, 2, buf, OLED_ASCIIFONTSIZE_8_0806, OLED_COLOR_BLUE);
        sprintf(buf, "Tem: %.2lf", env.Tem / 100.0);
        oled_showASCIIString(69, 2, buf, OLED_ASCIIFONTSIZE_8_0806, OLED_COLOR_BLUE);
        sprintf(buf, "Atm: %d", env.Atm / 100);
        oled_showASCIIString(5, 18, buf, OLED_ASCIIFONTSIZE_8_0806, OLED_COLOR_BLUE);
        sprintf(buf, "Hum: %.2lf", env.Hum / 100.0);
        oled_showASCIIString(69, 18, buf, OLED_ASCIIFONTSIZE_8_0806, OLED_COLOR_BLUE);
        sprintf(buf, "Alt: %d", env.Alt / 100);
        oled_showASCIIString(5, 34, buf, OLED_ASCIIFONTSIZE_8_0806, OLED_COLOR_BLUE);
        oled_refresh();
        // 调试输出
        printf("卡片{ 类型: %u, 卡号: %u }", card.cardType, card.cardID);
        printf("环境{ 照度: %dlux, 温度: %.2lf°C 气压: %dpa 湿度: %.2lf%% 海拔: %dm }\n", env.Lux / 100, env.Tem / 100.0, env.Atm / 100, env.Hum / 100.0, env.Alt);
        // 延时等待
        delay_ms(500);
    }
}
